home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
130 MIDI Tool Box
/
130 MIDI Tool Box.iso
/
midiexsr
/
midiint.asm
< prev
next >
Wrap
Assembly Source File
|
1986-11-14
|
11KB
|
373 lines
PAGE 60,132
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; MIDIINT.ASM -- Assembler subroutines for MIDIEX patch exchange utility
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; COPYRIGHT (C) 1986 John Bailin, Cantus Corporation
;
; Date: 01/02/86
;
; Changed 08/24/86 Jim Bergsten to function using the Microsoft "C"
; compiler. Summary of changes:
; 1. PAGE statement added for better output listing.
; 2. Entry point names prefixed with "_".
; 3. GROUP, PROG, SEGMENT statements changed to match Microsoft
; small model standards.
; 4. Unnecessary stack subtracts and adds removed.
; 5. Other corrections, simplifications...
;
; Changed 11/14/86 by Michael Geary - fixed several bugs
;
;
; Note: Linkage conventions assume the Microsoft C compiler small model.
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; equates
mpudata equ 330h ; mpu data port address.
mpustat equ 331h ; mpu status port address.
mpucmd equ 331h ; mpu command port address.
mpudsr equ 80h ; mpu data set ready, active low.
mpudrr equ 40h ; mpu data read ready, active low.
loop_delay equ 0ffffh ; delay for timeouts.
BUFMAX equ 8192 ; **MUST MATCH C CODE**
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_TEXT SEGMENT BYTE PUBLIC 'CODE'
_TEXT ENDS
CONST SEGMENT PARA PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT WORD PUBLIC 'BSS'
_BSS ENDS
_DATA SEGMENT WORD PUBLIC 'DATA'
_DATA ENDS
DGROUP GROUP CONST, _BSS, _DATA
ASSUME cs:_TEXT, ds:DGROUP, es:nothing, ss:nothing
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; data segment
_DATA segment word public 'DATA'
public _recv_data_count,_recv_buf,_recv_buf_ptr
public _fetch_buf_ptr
public _wait_char
oldInt2 label dword
int_2_save dw ?,?
_recv_buf db BUFMAX dup (0)
_recv_buf_end label byte
_recv_data_count dw 0
_recv_buf_ptr dw 0
_fetch_buf_ptr dw 0
_wait_char db 0
_DATA ends
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; code segment
_TEXT segment byte public 'CODE'
public _set_mpu_vector,_reset_mpu_vector,mpu_int,_int10
public _write_mpu_command,_write_mpu_data,_get_char
public _queue_mpu_data
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Set the interrupt vector for the MPU/401
_set_mpu_vector proc near
mov ax,350ah ; get current int 2
int 21h ; dos does it.
mov int_2_save,bx ; save the vector offset.
mov int_2_save+2,es ; save the vector segment.
push ds ; save data segment.
mov dx,offset mpu_int ; offset for dos call.
mov ax,seg mpu_int ; segment for dos call
mov ds,ax ;
mov ax,250ah ; set vector call, int 2.
int 21h ; dos installs vector.
pop ds
cli ; interrupts off.
in al,21h ; read 8259 address.
jmp short $+2
and al,0fbh ; enable irq2.
out 21h,al ;
call _mpu_reset ; reset the mpu, return code in AX
sti ; interrupts back on.
ret ; return to caller.
_set_mpu_vector endp
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Reset the interrupt vector for the MPU/401
_reset_mpu_vector proc near
push ds ; save registers.
cli ; interrupts off.
in al,21h ; read 8259.
jmp short $+2
or al,4 ; disable irq2.
out 21h,al ; done.
sti ; interrupts back on.
mov ax,250ah ; restore old int 2 vector.
mov dx,int_2_save ; get old offset into dx.
mov ds,int_2_save+2 ; get old segment into ds.
int 21h ; dos sets the vector.
pop ds ; restore registers.
ret ; return to caller.
_reset_mpu_vector endp
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Reset the MPU/401
_mpu_reset proc near
cli ; disable interrupts.
mov dx,mpustat ; mpu status port.
mov cx,loop_delay ; delay counter.
mr10: in al,dx ; get the status.
and al,mpudrr ; test for data receive ready.
jz mr15 ; ready.
loop mr10 ; not ready.
xor ax,ax ; timed out.
jmp short mr40 ; leave.
mr15: mov ax,0ffh ; get the command.
out dx,al ; send to mpu.
mov cx,loop_delay ; delay counter.
mr20: in al,dx ; get the status.
and al,mpudsr ; test for data set ready.
jz mr30 ; ready.
loop mr20 ; not ready.
xor ax,ax ; timed out.
jmp short mr40 ; leave.
mr30: mov dx,mpudata ; mpu data port.
in al,dx ; read data.
mov ax, 1
mr40:
sti ; interrupts back on.
ret ; return to caller.
_mpu_reset endp
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Write a command to the MPU
; BOOL write_mpu_command( command-byte );
_write_mpu_command proc near
push bp ; save caller's base pointer
mov bp,sp ; establish new base pointer.
mov dx,mpustat ; mpu status port.
mov cx,loop_delay ; loop counter for no response.
wmc10: in al,dx ; get the status.
and al,mpudrr ; test for data receive ready.
jz wmc15 ; ready.
loop wmc10 ; not ready.
xor ax,ax ; timed out.
jmp short wmc30 ; leave.
wmc15: cli ; interrupts off.
mov ax,[bp+4] ; get the command.
out dx,al ; send to mpu.
mov cx,loop_delay ; loop counter for no response.
wmc20: in al,dx ; get the status.
and al,mpudsr ; test for data set ready.
jz wmc25 ; ready.
loop wmc20 ; not ready.
xor ax,ax ; timed out.
jmp short wmc30 ; leave.
wmc25: mov dx,mpudata ; mpu data port.
in al,dx ; read data.
cmp al,0FEh ; acknowledge?
je wmc29 ; yes.
call _queue_mpu_data ; no. queue the data.
wmc29: mov ax,1 ; normal return
wmc30: sti ; interrupts back on.
pop bp ; get base pointer back.
ret ; return to caller.
_write_mpu_command endp
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Write data to the MPU
; BOOL write_mpu_data( data-byte );
_write_mpu_data proc near
push bp ; save caller's base pointer
mov bp,sp ; establish new base pointer.
mov dx,mpustat ; mpu status port.
mov cx,loop_delay ; loop counter for no response.
wmd10: in al,dx ; get the status.
and al,mpudrr ; test for data receive ready.
jz wmd20 ; ready.
loop wmd10 ; not ready.
xor ax,ax ; timed out.
jmp short wmd30 ; leave.
wmd20: mov dx,mpudata ; mpu data port.
mov ax,[bp+4] ; get the byte to send.
out dx,al ; send to mpu.
mov ax,1 ; normal return
wmd30: pop bp ; get base pointer back.
ret ; return to caller.
_write_mpu_data endp
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; MPU interrupt handler (IRQ2, INT 0Ah)
mpu_int proc far
push ax ; save regs.
push dx
pushf
mov dx,mpustat ; mpu status port
in al,dx ; read status
rol al,1 ; bit 7 into cy.
jb mi90 ; not generated by mpu.
popf
sti ; allow other interrupts
push ds
mov ax,DGROUP
mov ds,ax
mov dx,mpudata ; ready. now get data port.
in al,dx ; get data.
cmp al,0FEh ; acknowledge?
je mi30 ; yes. don't queue data.
cmp _wait_char,0 ; waiting for a particular char?
je mi20 ; no.
cmp al,_wait_char ; the char we're waiting for?
jne mi20 ; no.
mov _wait_char,0 ; yes. reset flag.
mi20: call _queue_mpu_data ; queue it up.
mi30: mov al,20h ; eoi to send to 8259.
out 20h,al ; send it.
pop ds ; restore regs.
pop dx
pop ax
iret ; return to caller.
mi90: popf
pop dx
pop ax
jmp oldInt2
mpu_int endp
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; queue received mpu data
; input -- al = received data
_queue_mpu_data proc near
push bx ; save regs
cli ; interrupts off.
mov bx,_recv_buf_ptr ; buffer ptr.
mov _recv_buf[bx],al ; store data.
inc _recv_buf_ptr ; increment the buffer pointer.
inc _recv_data_count ; increment the data count.
cmp _recv_buf_ptr,BUFMAX ; incremented past the end?
jb qmd10 ; not yet.
mov _recv_buf_ptr,0 ; yes. wrap around to zero.
qmd10: sti ; interrupts back on.
pop bx
ret ; return to caller.
_queue_mpu_data endp
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; fetch received mpu data (*not used*)
;
; input -- none
; output -- ah = 1 if data received, 0 if not. al = data.
IF 0
_fetch_mpu_data proc near
xor ax, ax
cli ; interrupts off.
mov bx,_fetch_buf_ptr ; buffer ptr.
cmp bx,_recv_buf_ptr ; any data?
je fmd10 ; no, return
mov al,_recv_buf[bx] ; fetch data.
mov ah, 1
inc _fetch_buf_ptr ; increment the buffer pointer.
cmp _fetch_buf_ptr,_recv_buf_end ; incremented past the end?
jb fmd10 ; not yet.
mov _fetch_buf_ptr,0 ; yes. wrap around to zero.
fmd10: sti ; interrupts back on.
ret ; return to caller.
_fetch_mpu_data endp
ENDIF
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; bios int 16h call.
;
; calling convention get_char( mode ) ;
;
; input -- mode = 0 -- read next char, return result in al, scan code in ah.
; -- mode = 1 -- returns 1 if a char is available, 0 if not.
; -- mode = 2 -- returns shift flags in al.
_get_char proc near
push bp ; save caller's base pointer
mov bp,sp ; establish new base pointer.
mov ax,[bp+4] ; get mode.
xchg ah,al ; turn it around for bios call.
int 16h ; do the bios call.
pushf ; save flags.
cmp word ptr [bp+4],1 ; check for char available?
jne gc10 ; no. just return what bios returns.
xor ax,ax ; assume no char.
popf ; get flags back.
jz gc20 ; no char available.
mov ax,1 ; signal char available.
jmp short gc20 ; continue.
gc10: popf ; sync.
gc20: pop bp ; get base pointer back.
ret ; return to caller.
_get_char endp
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; bios int 10h c level call.
;
; calling convention int10( ax, bx, cx, dx )
;
_int10 proc near
push bp ; save caller's base pointer
mov bp,sp ; establish new base pointer.
mov ax,[bp+4] ; get register calling value.
mov bx,[bp+6] ; get register calling value.
mov cx,[bp+8] ; get register calling value.
mov dx,[bp+10] ; get register calling value.
int 10h ; do the bios call.
pop bp ; get base pointer back.
ret ; return to caller.
_int10 endp
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
_TEXT ends
end